package com.cloudOffice.interceptor;

import com.cloudOffice.constant.HttpConstant;
import com.cloudOffice.enumeration.ResultCodeEnum;
import com.cloudOffice.execption.CustomException;
import com.cloudOffice.storage.CommonStorage;
import com.cloudOffice.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * jwt令牌校验的拦截器
 */
@Slf4j
@Component
public class JwtTokenInterceptor implements HandlerInterceptor {
	
	@Resource
	private RedisTemplate<String, String> redisTemplate;
	
	/**
	 * 校验jwt
	 */
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
		//判断当前拦截到的是Controller的方法还是其他资源
		if (!(handler instanceof HandlerMethod)) {
			//当前拦截到的不是动态方法，直接放行
			return true;
		}
		String token = request.getHeader("Authorization");
		log.info("token令牌：{}", token);
		if (token == null || token.isEmpty()) {
			log.error("令牌为空，请求被拦截");
			response.setStatus(HttpConstant.CODE_401);
			throw new CustomException(ResultCodeEnum.PERMISSION);
		}
		try {
			//校验令牌
			Map<String, Object> map = JwtUtils.parse(token);
			log.info("解析后的令牌：{}", map);
			Object id = map.get("id");
			log.info("id：{}", id);
			String username = (String) map.get("username");
			log.info("登录账户：id：{}, username: {}", id, username);
			String oldToken = redisTemplate.opsForValue().get(id + username);
			log.info("oldToken：{}", oldToken);
			if (oldToken == null) {
				CommonStorage.setId(id);
				CommonStorage.setUsername(username);
				redisTemplate.opsForValue().set(id + username, token, (Long) map.get("exp"), TimeUnit.SECONDS);
				return true;
			}
			Claims claims = JwtUtils.parse(oldToken);
			if (id.equals(claims.get("id")) && username.equals(claims.get("username")) && !token.equals(oldToken)) {
				response.setStatus(HttpConstant.CODE_401);
				log.error("账号异地登录，请重新登录");
				throw new CustomException(ResultCodeEnum.REMOTE_LOGIN);
			}
			CommonStorage.setId(id);
			CommonStorage.setUsername(username);
			// 令牌校验通过，放行
			return true;
		} catch (ExpiredJwtException e) {
			log.error("令牌过期：{}", e.getMessage());
			response.setStatus(HttpConstant.CODE_401);
			throw new CustomException(ResultCodeEnum.TOKEN_INVALID);
		}
	}
	
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
	                            Exception ex) {
		CommonStorage.removeId();
		CommonStorage.removeUsername();
	}
}
